package br.cin.stadium.application.activities;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.PixelFormat;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import br.cin.stadium.application.R;
import br.cin.stadium.application.util.Logger;
import br.cin.stadium.middleware.StadiumException;
import br.cin.stadium.middleware.StadiumTS;
import br.cin.stadium.middleware.media.Media;
import br.cin.stadium.middleware.media.MediaReference;


public class VideoPlayer extends Activity implements OnErrorListener,
		OnBufferingUpdateListener, OnCompletionListener,
		MediaPlayer.OnPreparedListener, SurfaceHolder.Callback
{
	private static final String TAG = "VideoPlayer";

	private MediaPlayer mp;
	private SurfaceView mPreview;
	private TextView mMedia;
	private SurfaceHolder holder;
	private Button mPlay;
	private Button mPause;
	private Button mReset;
	private Button mStop;
	private String currentMediaName;
	private MediaReference mediaRef;
	
	private ProgressDialog pd;
	private DownloadVideoThread downloadThread = null;

	/**
	 * Called when the activity is first created.
	 */
	public void onCreate(Bundle icicle)
	{
		Logger.log("VideoPlayer", "onCreate", "Begin");

		super.onCreate(icicle);
		setContentView(R.layout.videoplayer);

		mediaRef = new MediaReference();
		mediaRef.getServerLocation().setIp(getIntent().getExtras().getString("mediaIp"));
		mediaRef.getServerLocation().setPort(getIntent().getExtras().getString("mediaPort"));
		mediaRef.setMediaName(getIntent().getExtras().getString("mediaName"));
		mediaRef.setSector(getIntent().getExtras().getInt("mediaSector"));

		// Set up the play/pause/reset/stop buttons
		mPreview = (SurfaceView) findViewById(R.id.VideoView01);
		mMedia = (TextView) findViewById(R.id.TextViewMedia);
		mMedia.setText("Name: " + mediaRef.getMediaName() + " from: " + mediaRef.getServerLocation().getIp());
		mPlay = (Button) findViewById(R.id.ButtonPlay);
		mPause = (Button) findViewById(R.id.ButtonPause);
		mReset = (Button) findViewById(R.id.ButtonReset);
		mStop = (Button) findViewById(R.id.ButtonStop);

		mPlay.setOnClickListener(new View.OnClickListener()
		{
			public void onClick(View view)
			{
				playVideo();
			}
		});
		mPause.setOnClickListener(new View.OnClickListener()
		{
			public void onClick(View view)
			{
				if (mp != null)
				{
					mp.pause();
				}
			}
		});
		mReset.setOnClickListener(new View.OnClickListener()
		{
			public void onClick(View view)
			{
				if (mp != null)
				{
					mp.seekTo(0);
				}
			}
		});
		mStop.setOnClickListener(new View.OnClickListener()
		{
			public void onClick(View view)
			{
				if (mp != null)
				{
					mp.seekTo(0);
					if (mp.isPlaying())
					{
						mp.pause();						
					}					
				}
			}
		});

		// Set the transparency
		getWindow().setFormat(PixelFormat.TRANSPARENT);

		// Set a size for the video screen
		holder = mPreview.getHolder();
		holder.addCallback(this);
		holder.setFixedSize(400, 300);
		
		Logger.log("VideoPlayer", "onCreate", "End");
	}

	private void playVideo()
	{
		Logger.log("VideoPlayer", "playVideo", "Begin");
		
		try
		{
			// If the path has not changed, just start the media player
			if (mediaRef.getMediaName().equals(currentMediaName) && mp != null)
			{
				mp.start();
				return;
			}
			
			currentMediaName = mediaRef.getMediaName();

			// Create a new media player and set the listeners
			mp = new MediaPlayer();
			mp.setOnErrorListener(this);
			mp.setOnBufferingUpdateListener(this);
			mp.setOnCompletionListener(this);
			mp.setOnPreparedListener(this);

			// Set the surface for the video output
			mp.setDisplay(mPreview.getHolder());

			pd = ProgressDialog.show(this, "Loading.", "Loading video, please wait...", true, false);
			downloadThread = new DownloadVideoThread();			
			new Thread(downloadThread).start();
			
		} catch (Exception e)
		{
			Log.e(TAG, "error: " + e.getMessage(), e);
			if (mp != null)
			{
				mp.stop();
				mp.release();
			}
		}

		Logger.log("VideoPlayer", "playVideo", "End");
		
	}

	/**
	 * If the user has specified a local url, then we download the url stream to
	 * a temporary location and then call the setDataSource for that local file
	 * 
	 * @param path
	 * @throws IOException
	 */
	private void setDataSource(String path) throws IOException
	{
		Logger.log("VideoPlayer", "setDataSource", "Begin (" + path + ")");

		if (path.equals(""))
		{
			
			Media media = null;
			try {
				media = StadiumTS.getInstance().requestMedia(mediaRef);
			} catch (StadiumException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			File temp = File.createTempFile("mediaplayertmp", ".dat", this
					.getCacheDir());
			String tempPath = temp.getAbsolutePath();
			FileOutputStream out = new FileOutputStream(temp);
			out.write(media.getContent());
			out.flush();
			out.close();
			Log.v(TAG, "File " + temp.getName() + " downloaded to " + tempPath + " size: " + temp.length());

			// Give permission to access the file
			String command = "chmod 666 " + tempPath;
			Logger.log("VideoPlayer", "setDataSource", "changing the file permission.");
			try
			{
				Runtime.getRuntime().exec(command);
			} catch (IOException e1)
			{
				Log.e(TAG, "Couldn't set permissions", e1);
			}
			Logger.log("VideoPlayer", "setDataSource", "file permission changed.");
			mp.setDataSource(tempPath);
		}
		
		Logger.log("VideoPlayer", "setDataSource", "End");
	}

	public boolean onError(MediaPlayer mediaPlayer, int what, int extra)
	{
		Logger.log("VideoPlayer", "onError", "Begin (" + mediaPlayer + "," + what + "," + extra + ")");

		Log.e(TAG, "onError--->   what:" + what + "    extra:" + extra);
		if (mediaPlayer != null)
		{
			System.out.println("VAI PARA MEDIA PLAYER");
			mediaPlayer.stop();
			mediaPlayer.release();
		}

		Logger.log("VideoPlayer", "onError", "End");
		return true;
	}

	public void onBufferingUpdate(MediaPlayer arg0, int percent)
	{
		Logger.log("VideoPlayer", "onBufferingUpdate", "(" + percent + ")");
		Log.d(TAG, "onBufferingUpdate called --->   percent:" + percent);
	}

	public void onCompletion(MediaPlayer arg0)
	{
		Logger.log("VideoPlayer", "onCompletion", "");
		Log.d(TAG, "onCompletion called");
	}

	public void onPrepared(MediaPlayer mediaplayer)
	{
		Logger.log("VideoPlayer", "onPrepared", "");
		Log.d(TAG, "onPrepared called");
	}

	public void surfaceCreated(SurfaceHolder surfaceholder)
	{
		Logger.log("VideoPlayer", "surfaceCreated", "");
		Log.d(TAG, "surfaceCreated called");
	}

	public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k)
	{
		Logger.log("VideoPlayer", "surfaceChanged", "");
		Log.d(TAG, "surfaceChanged called");
	}

	public void surfaceDestroyed(SurfaceHolder surfaceholder)
	{
		Logger.log("VideoPlayer", "surfaceDestroyed", "");
		Log.d(TAG, "surfaceDestroyed called");
	}
	
	class DownloadVideoThread implements Runnable
	{

		public void run()
		{
			Logger.log("VideoPlayer-->DownloadVideoThread", "run", "Begin");
			try
			{
				setDataSource("");
				mp.prepare();
			} catch (IOException e)
			{
				Log.e(TAG, e.getMessage(), e);
			}
			finally
			{
				handler.sendEmptyMessage(0);				
			}
			Log.v(TAG, "Duration:  ===>" + mp.getDuration());			
			mp.start();
			Logger.log("VideoPlayer-->DownloadVideoThread", "run", "End(Apos Start)");
		}		
	}
	
	private Handler handler = new Handler() 
	{
		@Override
		public void handleMessage(Message msg) 
		{
			pd.dismiss();
		}
	};
	
	@Override
	protected void onStop()
	{
		super.onStop();
		Logger.log("VideoPlayer", "onStop", "Parar o VideoPlayer activity.");
		if (mp != null)
		{
			mp.release();			
		}		
	}
}